#ifndef xpack_graphic_draw_circular
#define xpack_graphic_draw_circular
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::graphic_draw_circular::inc
#include"define/base_type.hpp"
#include"graphic/draw/circular_eighth.hpp"
#include"graphic/private/rander_helper.hpp"
#include"graphic/rander_wrapper.hpp"
#include"macro/xexport.hpp"
#include"math/point.hpp"
#include"utils/memory.hpp"
#pragma pop_macro("xuser")

namespace mixc::graphic_draw_circular::inc{
    template<bool texturing_v, class rander_t>
    inline void circular_core(inc::pt2wx p, uxx r, rander_t const & rander){
        auto last_y0        = ixx{};
        auto last_y1        = ixx{};
        auto last_y2        = ixx{};
        auto last_y3        = ixx{};

        inc::draw::circular_eighth(r, [&](auto x, auto y){
            auto x0         = p->x - x;
            auto x1         = p->x + x - 1; // 需要 - 1，这样 texuring 步骤的 width 才正常
            auto y0         = p->y - y;
            auto y1         = p->y + y - 1;

            auto x2         = p->x - y;
            auto x3         = p->x + y - 1;
            auto y2         = p->y - x;
            auto y3         = p->y + x - 1;

            rander(x0, y0);
            rander(x1, y0);
            rander(x0, y1);
            rander(x1, y1);

            rander(x2, y2);
            rander(x3, y2);
            rander(x2, y3);
            rander(x3, y3);

            // 注意:
            // 使用显式 texturing 而非通用 texturing 以便能有更好的性能
            if constexpr (texturing_v and inc::is_rander_wrapper<rander_t>){
                if (inc::rander_helper::get_texture_mode(rander) == inc::texture_mode_t::none){
                    return;
                }
                else{
                    auto width0 = x + x - 2;
                    auto width1 = y + y - 2;

                    if (last_y0 != y0){
                        rander.texturing(x0 + 1, y0, width0);
                    }
                    if (last_y1 != y1){
                        rander.texturing(x0 + 1, y1, width0);
                    }
                    if (last_y2 != y2){
                        rander.texturing(x2 + 1, y2, width1);
                    }
                    if (last_y3 != y3){
                        rander.texturing(x2 + 1, y3, width1);
                    }
                }

                last_y0     = y0;
                last_y1     = y1;
                last_y2     = y2;
                last_y3     = y3;
            }
        });
    }
}

namespace mixc::graphic_draw_circular::origin{
    template<class rander_t>
    inline void circular(inc::pt2wx p, uxx r, rander_t const & rander){
        if (auto thickness = inc::rander_helper::get_thickness(rander); thickness != 1){
            inc::rander_helper::thickening(rander, [&](auto const & outside_rander, auto const & inside_rander){
                inc::circular_core<false>(p, r + thickness - 1, outside_rander);
                inc::circular_core<true>(p, r, inside_rander);
            });
        }
        else{
            inc::circular_core<true>(p, r, rander);
        }
    }

    template<class rander_t>
    inline void circular(uxx r, rander_t const & rander){
        circular({}, r, rander);
    }
}
#endif

xexport_spacex(draw, mixc::graphic_draw_circular::origin)
